﻿using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.Extensions.DependencyInjection;

namespace Luka;

[NotScanned]
internal sealed class AuthorizationHandler : IAuthorizationHandler
{
    /// <summary>
    /// 创建自定义的授权策略和要求
    /// </summary>
    /// <param name="context"></param>
    /// <returns></returns>
    public async Task HandleAsync(AuthorizationHandlerContext context)
    {
        var filterContext = context.Resource as AuthorizationFilterContext;
        var httpContext = filterContext?.HttpContext;
        var jwtBearerService = httpContext?.RequestServices.GetService<IJwtBearerService>();
        if (jwtBearerService != null)
        {
            // 自动刷新 Token 逻辑
            if (httpContext != null && !jwtBearerService.AutoRefreshToken(context, httpContext))
            {
                if (httpContext != null)
                {
                    // 退出 Swagger 登录
                    httpContext.Response.Headers["access-token"] = "invalid_token";
                    context.Fail();
                }
                return;
            }

            // 获取所有未成功验证的需求
            var pendingRequirements = context.PendingRequirements;

            // 获取 JWT 处理类
            var jwtBearerHandle = httpContext?.RequestServices.GetService<IJwtBearerHandler>();

            if (httpContext != null && jwtBearerHandle != null)
            {
                Exception? authorizeException = null;

                bool isAuthorizeSuccess;
                try
                {
                    isAuthorizeSuccess = await jwtBearerHandle.AuthorizeHandle(context, httpContext);
                }
                catch (Exception ex)
                {
                    isAuthorizeSuccess = false;
                    authorizeException = ex;
                }

                // 授权检测
                if (isAuthorizeSuccess)
                {
                    // 判断是否跳过权限检查
                    if (filterContext?.HasAttribute<SkipPermissionAttribute>() == true)
                    {
                        foreach (var requirement in pendingRequirements)
                        {
                            context.Succeed(requirement);
                        }
                    }
                    else
                    {
                        foreach (var requirement in pendingRequirements)
                        {
                            bool isPermissionSuccess;
                            Exception? permissionException = default;
                            try
                            {
                                isPermissionSuccess = await jwtBearerHandle.PermissionHandle(context, requirement, httpContext);
                            }
                            catch (Exception ex)
                            {
                                isPermissionSuccess = false;
                                permissionException = ex;
                            }

                            // 权限检测
                            if (isPermissionSuccess)
                            {
                                context.Succeed(requirement);
                            }
                            else
                            {
                                var result = await jwtBearerHandle.PermissionFailHandle(context, requirement, httpContext, permissionException);

                                if (result != null)
                                {
                                    // 存在自定义处理结果，则返回 403 状态码
                                    httpContext.Response.StatusCode = StatusCodes.Status403Forbidden;
                                    filterContext?.ReturnResult(result, true);
                                }
                                else
                                {
                                    // 权限判断失败，返回 403 状态码
                                    context.Fail();
                                }
                            }
                        }
                    }
                }
                else
                {
                    var result = await jwtBearerHandle.AuthorizeFailHandle(context, httpContext, authorizeException);
                    if (result != null)
                    {
                        // 存在自定义处理结果，则返回 401 状态码
                        httpContext.Response.StatusCode = StatusCodes.Status401Unauthorized;
                        filterContext?.ReturnResult(result, true);
                    }
                    else
                    {
                        // 授权失败，返回 403 状态码
                        context.Fail();
                    }
                }
            }
            else
            {
                foreach (var requirement in pendingRequirements)
                {
                    context.Succeed(requirement);
                }
            }
        }
    }
}